// /////////////////////////////////////////////////////////////////////////////
//
// Name:            asEventManager.cpp
// Author:          Michael Bartsch (ZCCdark203)
//
// Desc :           Binds the EventManager class to AngelScript
//
// License:         Copyright (C) 2009 Michael Bartsch and Contributors
//
//                  This program is free software: you can redistribute it
//                  and/or modify it under the terms of the zlib/libpng License.
//                  See main.cpp for conditions of distribution and use.
//
// /////////////////////////////////////////////////////////////////////////////

// Include files
#include "asEventManager.h"

#ifdef __COMPILE_WITH_ANGELSCRIPT__

#include "../../core/GameManager.h"
#include "ScriptedEvent.h"

//! Wrapper function to allow script-side classes to connect event signals.
//! @note For internal use only!
bool connectEventSignal(const std::string &groupName, const std::string &slotName,
                        asIScriptObject *object, const std::string &function,
                        EventManager *pEventMgr)
{
    // Create a ScriptedEvent instance.
    ScriptedEvent *scriptedEvent = new ScriptedEvent(object, function);

    // Connect our wrapper function to the appropriate slots.
    if(pEventMgr->connectEventSignal(groupName, slotName, scriptedEvent, &ScriptedEvent::onEvent))
    {
       // Set up the disconnect slot.
       std::stringstream ss;
       ss << slotName << "#disconnect[" << object->GetTypeId() << "-"
          << object->GetObjectType()->GetMethodIdByName(function.c_str()) << "]";

       pEventMgr->createEventSlot(groupName, ss.str());
       pEventMgr->connectEventSignal(groupName, ss.str(), scriptedEvent, &ScriptedEvent::onDisconnect);

       // We've succeeded.
       return true;
    }

    else
    {
       scriptedEvent->drop();
       return false;
    }
}

//! Wrapper function to allow script-side classes to disconnect event signals.
//! @note For internal use only!
void disconnectEventSignal(const std::string &groupName, const std::string &slotName,
                           asIScriptObject *object, const std::string &function,
                           EventManager *pEventMgr)
{
    // Emit the disconnect event.
    std::stringstream ss;
    ss << slotName << "#disconnect[" << object->GetTypeId() << "-"
       << object->GetObjectType()->GetMethodIdByName(function.c_str()) << "]";

    pEventMgr->emitEvent(groupName, ss.str());

    // Remove the disconnect slot.
    pEventMgr->removeEventSlot(groupName, ss.str());
}


//! Binds the EventManager class to AngelScript.
void bindEventManager(asIScriptEngine *engine)
{
    // Forward declarations.
    int r;

    // Bind EventManager class.
    r = engine->RegisterObjectType("EventManager", sizeof(EventManager), asOBJ_REF); assert(r >= 0);

    // Set EventManager behaviour.
    r = engine->RegisterObjectBehaviour("EventManager", asBEHAVE_ADDREF, "void f()",
                                        asMETHOD(EventManager, grab), asCALL_THISCALL); assert(r >= 0);
    r = engine->RegisterObjectBehaviour("EventManager", asBEHAVE_RELEASE, "void f()",
                                        asMETHOD(EventManager, drop), asCALL_THISCALL); assert(r >= 0);

    // Bind EventManager class functions.
    r = engine->RegisterObjectMethod("EventManager", "void init()",
                                     asMETHOD(EventManager, init), asCALL_THISCALL); assert(r >= 0);
    r = engine->RegisterObjectMethod("EventManager", "void clear()",
                                     asMETHOD(EventManager, clear), asCALL_THISCALL); assert(r >= 0);

    r = engine->RegisterObjectMethod("EventManager", "bool createEventGroup(const string &in)",
                                     asMETHOD(EventManager, createEventGroup), asCALL_THISCALL); assert(r >= 0);
    r = engine->RegisterObjectMethod("EventManager", "bool createEventSlot(const string &in, const string &in)",
                                     asMETHOD(EventManager, createEventSlot), asCALL_THISCALL); assert(r >= 0);

    r = engine->RegisterObjectMethod("EventManager", "bool connectEventSignal(const string &in, " \
                                     "const string &in, IHasSlots@, const string &in)",
                                     asFUNCTION(connectEventSignal), asCALL_CDECL_OBJLAST); assert(r >= 0);
    r = engine->RegisterObjectMethod("EventManager", "void disconnectEventSignal(const string &in, " \
                                     "const string &in, IHasSlots@, const string &in)",
                                     asFUNCTION(disconnectEventSignal), asCALL_CDECL_OBJLAST); assert(r >= 0);

    r = engine->RegisterObjectMethod("EventManager", "bool getIsKeyDown(EKEY_CODE)",
                                     asMETHOD(EventManager, getIsKeyDown), asCALL_THISCALL); assert(r >= 0);
    r = engine->RegisterObjectMethod("EventManager", "bool getIsKeyUp(EKEY_CODE)",
                                     asMETHOD(EventManager, getIsKeyDown), asCALL_THISCALL); assert(r >= 0);

    r = engine->RegisterObjectMethod("EventManager", "s32 getMouseX()",
                                     asMETHOD(EventManager, getMouseX), asCALL_THISCALL); assert(r >= 0);
    r = engine->RegisterObjectMethod("EventManager", "s32 getMouseY()",
                                     asMETHOD(EventManager, getMouseY), asCALL_THISCALL); assert(r >= 0);
    r = engine->RegisterObjectMethod("EventManager", "const vector2di& getMousePos()",
                                     asMETHOD(EventManager, getMousePos), asCALL_THISCALL); assert(r >= 0);
    r = engine->RegisterObjectMethod("EventManager", "f32 getMouseWheel()",
                                     asMETHOD(EventManager, getMouseWheel), asCALL_THISCALL); assert(r >= 0);

    r = engine->RegisterObjectMethod("EventManager", "void removeEventGroups()",
                                     asMETHOD(EventManager, removeEventGroups), asCALL_THISCALL); assert(r >= 0);
    r = engine->RegisterObjectMethod("EventManager", "bool removeEventSlots(const string &in)",
                                     asMETHOD(EventManager, removeEventSlots), asCALL_THISCALL); assert(r >= 0);
    r = engine->RegisterObjectMethod("EventManager", "bool removeEventGroup(const string &in)",
                                     asMETHOD(EventManager, removeEventGroup), asCALL_THISCALL); assert(r >= 0);
    r = engine->RegisterObjectMethod("EventManager", "bool removeEventSlot(const string &in, const string &in)",
                                     asMETHOD(EventManager, removeEventSlot), asCALL_THISCALL); assert(r >= 0);
}

#endif // __COMPILE_WITH_ANGELSCRIPT__

// End of File
